/*
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is MPEG4IP.
 *
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 * Portions created by Cisco Systems Inc. are
 * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
 *
 * Contributor(s):
 *      Dave Mackie     dmackie@cisco.com
 */

#ifndef MP4V2_IMPL_MP4UTIL_H
#define MP4V2_IMPL_MP4UTIL_H

namespace mp4v2
{
    namespace impl
    {

        ///////////////////////////////////////////////////////////////////////////////

#include <assert.h>

#define LIBMPV42_STRINGIFY(x)  #x

#ifndef ASSERT
#   define ASSERT(expr) \
        if (!(expr)) { \
            throw new Exception("assert failure: "LIBMPV42_STRINGIFY((expr)), __FILE__, __LINE__, __FUNCTION__ ); \
        }
#endif

#define WARNING(expr) \
    if (expr) { \
        log.errorf("Warning (%s) in %s at line %u", \
                         LIBMPV42_STRINGIFY(expr), __FILE__, __LINE__); \
    }

        ///////////////////////////////////////////////////////////////////////////////

#define CHECK_AND_FREE(a) if ((a) != NULL) { free((void *)(a)); (a) = NULL;}

#define NUM_ELEMENTS_IN_ARRAY(name) ((sizeof((name))) / (sizeof(*(name))))

        ///////////////////////////////////////////////////////////////////////////////

        inline void *MP4Malloc(size_t size)
        {
            if (size == 0) return NULL;
            void *p = malloc(size);
            if (p == NULL && size > 0)
            {
                log.errorf("MP4Malloc size=%d\n", size);
                throw new PlatformException("malloc failed", errno, __FILE__, __LINE__, __FUNCTION__);
            }
            return p;
        }

        inline void *MP4Calloc(size_t size)
        {
            if (size == 0) return NULL;
            return memset(MP4Malloc(size), 0, size);
        }

        inline char *MP4Stralloc(const char *s1)
        {
            char *s2 = (char *)MP4Malloc(strlen(s1) + 1);
            strcpy(s2, s1);
            return s2;
        }

        inline void *MP4Realloc(void *p, uint32_t newSize)
        {
            // workaround library bug
            if (p == NULL && newSize == 0)
            {
                return NULL;
            }

            void *temp = realloc(p, newSize);
            if (temp == NULL && newSize > 0)
            {
                throw new PlatformException("malloc failed", errno, __FILE__, __LINE__, __FUNCTION__);
            }
            return temp;
        }

        uint32_t STRTOINT32( const char * );
        void     INT32TOSTR( uint32_t, char * );

        MP4Timestamp MP4GetAbsTimestamp();

        uint64_t MP4ConvertTime(uint64_t t,
                                uint32_t oldTimeScale, uint32_t newTimeScale);

        bool MP4NameFirstMatches(const char *s1, const char *s2);

        bool MP4NameFirstIndex(const char *s, uint32_t *pIndex);

        char *MP4NameFirst(const char *s);

        const char *MP4NameAfterFirst(const char *s);

        char *MP4ToBase16(const uint8_t *pData, uint32_t dataSize);

        char *MP4ToBase64(const uint8_t *pData, uint32_t dataSize);

        const char *MP4NormalizeTrackType(const char *type);

        ///////////////////////////////////////////////////////////////////////////////

    }
} // namespace mp4v2::impl

#endif // MP4V2_IMPL_MP4UTIL_H
